<?php
namespace support;

use JsonSerializable;

abstract class BaseData implements JsonSerializable
{
    /**
     * 支持从数组或对象创建 DTO
     */
    public static function from(array|object $data): static
    {
        if (is_object($data)) {
            $data = get_object_vars($data);
        }
        // 只取构造参数
        $ref = new \ReflectionClass(static::class);
        $params = $ref->getConstructor()?->getParameters() ?? [];
        $args = [];
        foreach ($params as $param) {
            $name = $param->getName();
            $args[] = $data[$name] ?? null;
        }
        return new static(...$args);
    }

    /**
     * 批量 from：二维数组转 DTO 数组
     * @param array $list
     * @return static[]
     */
    public static function fromList(array $list): array
    {
        $result = [];
        foreach ($list as $item) {
            $result[] = static::from($item);
        }
        return $result;
    }

    /**
     * 转数组
     */
    public function toArray(): array
    {
        return get_object_vars($this);
    }

    /**
     * 批量 transform：DTO 数组转二维数组
     * @param static[] $list
     * @param array|null $fields 指定字段（可选）
     * @return array
     */
    public static function transformList(array $list, ?array $fields = null): array
    {
        $result = [];
        foreach ($list as $item) {
            $arr = $item instanceof self ? $item->toArray() : (array)$item;
            if ($fields) {
                $arr = array_intersect_key($arr, array_flip($fields));
            }
            $result[] = $arr;
        }
        return $result;
    }

    /**
     * 转 json 字符串
     */
    public function toJson(int $options = JSON_UNESCAPED_UNICODE): string
    {
        return json_encode($this->toArray(), $options);
    }

    /**
     * 兼容 webman response->json() 直接传对象
     */
    public function jsonSerialize(): array
    {
        return $this->toArray();
    }

    /**
     * transform: 返回数组数据，便于链式调用
     * @param array|null $fields 指定字段（可选）
     */
    public function transform(?array $fields = null): array
    {
        $arr = $this->toArray();
        if ($fields) {
            $arr = array_intersect_key($arr, array_flip($fields));
        }
        return $arr;
    }
} 